
#include "pywinpcapmodule.h"

extern PyObject * PyExc_PyWinPCapError;
extern PyObject * PyExc_PyWinPCapTimeoutError;

static void
pywinpcap_packet_dealloc(pywinpcap_packet_object * self)
{
	Py_XDECREF(self->m_pkt_data);
	self->m_pkt_data = NULL;

    self->ob_type->tp_free((PyObject*)self);
}

static PyObject * pywinpcap_packet_new(	PyTypeObject * type,
										PyObject *args,
										PyObject *kwds)
{
    pywinpcap_packet_object * self = NULL;

    self = (pywinpcap_packet_object *)type->tp_alloc(type, 0);
    if (NULL == self)
	{
		return NULL;
	}

	self->m_pkt_data = (PyStringObject *)PyString_FromString("");
    if (NULL == self->m_pkt_data)
    {
		Py_DECREF(self);
        return NULL;
    }
    
    return (PyObject *)self;
}

static int pywinpcap_packet_init(	pywinpcap_packet_object * self,
									PyObject * args,
									PyObject * kwds)
{
    PyStringObject * pkt_data = NULL;
	PyObject * temp = NULL;
	
	self->m_timestamp.tv_usec = 0;
	if (!PyArg_ParseTuple(args, "Oi|i", &pkt_data, &self->m_timestamp.tv_sec, &self->m_timestamp.tv_usec))
	{
		return -1;
	}

	if (!PyString_Check(pkt_data))
	{
		return -1;
	}

    temp = (PyObject *)self->m_pkt_data;
    Py_INCREF(pkt_data);
    self->m_pkt_data = pkt_data;
    Py_XDECREF(temp);

    return 0;
}

static PyObject *
pywinpcap_packet_timestamp(pywinpcap_packet_object * self, PyObject * args)
{
	PyObject * ret = NULL;

	ret = PyTuple_New(2);
	if (NULL == ret)
	{
		return ret;
	}

	if ((0 != PyTuple_SetItem(ret, 0, PyLong_FromLong(self->m_timestamp.tv_sec))) ||
		(0 != PyTuple_SetItem(ret, 1, PyLong_FromLong(self->m_timestamp.tv_usec))))
	{
		Py_DECREF(ret);

		return NULL;
	}

	return ret;		
}

PyDoc_STRVAR(pywinpcap_packet_timestamp_doc,
"timestamp() -> Get packet timestamp");

static PyObject * pywinpcap_packet_str(pywinpcap_packet_object * self)
{
	return PyString_FromFormat("<Packet %d bytes (%d.%d)>", self->m_pkt_data->ob_size, self->m_timestamp.tv_sec, self->m_timestamp.tv_usec);
}

static PyMemberDef pywinpcap_packet_members[] = {
    {"data", T_OBJECT_EX, offsetof(pywinpcap_packet_object, m_pkt_data), 0, "packet data"},
    {NULL}  /* Sentinel */
};

static PyMethodDef pywinpcap_packet_methods[] = {
	{"timestamp",	(PyCFunction)pywinpcap_packet_timestamp,	METH_VARARGS,	pywinpcap_packet_timestamp_doc},
    {NULL}  /* Sentinel */
};

PyTypeObject pywinpcap_packet_type = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "pywinpcap.Packet",             /*tp_name*/
    sizeof(pywinpcap_packet_object), /*tp_basicsize*/
    0,                         /*tp_itemsize*/
	(destructor)pywinpcap_packet_dealloc,  /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    (reprfunc)pywinpcap_packet_str, /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    (reprfunc)pywinpcap_packet_str,  /*tp_str*/	
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
    "Packet object",           /* tp_doc */
    0,		               /* tp_traverse */
    0,		               /* tp_clear */
    0,		               /* tp_richcompare */
    0,		               /* tp_weaklistoffset */
    0,		               /* tp_iter */
    0,		               /* tp_iternext */
	pywinpcap_packet_methods,  /* tp_methods */
    pywinpcap_packet_members,  /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
	(initproc)pywinpcap_packet_init,	/* tp_init */
    0,                         /* tp_alloc */
	pywinpcap_packet_new,      /* tp_new */
};
